//
//  Deque.hpp
//  LLTryFightingApp
//
//  Created by jinbang.li on 2024/9/27.
//

#ifndef Deque_hpp
#define Deque_hpp

#include <stdio.h>
#include <iostream>

template <typename T>
class LLDeque {
private:
    struct Node {
        T data;
        Node* next;
        Node* prev;
        
        Node(T value):data(value),next(nullptr),prev(nullptr){}
    };
    
    Node *front;
    Node *back;
    
public:
    LLDeque():front(nullptr),back(nullptr){}
    ~LLDeque() {
        
    }
    bool isEmpty() {
        return front == nullptr;
    }
    
    void pushFront(T value) {
        Node *newNode = new Node(value);
        if (isEmpty()) {
            front = back = newNode;
        }else {
            newNode->next = front;
            front->prev = newNode;
            front = newNode;
        }
    }
    
    void pushBack(T value) {
        Node *newNode = new Node(value);
        if (isEmpty()) {
            front = back = newNode;
        }else {
            newNode->prev = back;
            back->next = newNode;
            back = newNode;
        }
    }
    
    void popFront(){
        if (isEmpty()) {
            std::cerr<<"Deque is empty,cannot pop from front" << std::endl;
            return;
        }
        Node *temp = front;
        front = front->next;
        if (front) {
            front->prev = nullptr;
        }else {
            back = nullptr;
        }
        delete temp;
    }
    void popBack() {
        if (isEmpty()) {
            std::cerr<<"Deque is empty,cannot pop from back" << std::endl;
            return;
        }
        Node *temp = back;
        back = back->prev;
        if (back) {
            back->next = nullptr;
        }else {
            front = nullptr;
        }
        delete temp;
    }
    
    T getFront() {
        if (isEmpty()) {
            throw std::runtime_error("deque is empty");
        }
        return front->data;
    }
    T getBack() {
        if (isEmpty()) {
            throw std::runtime_error("deque is empty");
        }
        return back->data;
    }
    
    void display() {
        Node *current = front;
        while (current) {
            std::cout << current->data << " ";
            current = current->next;
        }
        std::cout << std::endl;
    }
};
#endif /* Deque_hpp */
